#region Using Statements
using System;
using System.Collections.Generic;
using System.Linq;
using System.Media;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using System.Diagnostics;
using System.IO;
#endregion using

namespace Turn_ament
{
    public class Game : Microsoft.Xna.Framework.Game
    {
        #region Attributes
        GraphicsDeviceManager graphics; SpriteBatch spriteBatch;
        SpriteFont largeFont, mediumFont, normalFont, smallFont;
        Texture2D blank, soldierNinjaTex, soldierPandaTex, tankNinjaTex, tankPandaTex, rangeNinjaTex, rangePandaTex, instruct, instructButton, playButton, exitButton,
            credits, creditButton, menu, backButton, end, replayButton, forest, ground, mountain;
        Map map;
        Unit currentUnit; Tile currentTile;
        enum GameState { Menu, Credits, Instructions, Start, Game, GameBase, End }
        GameState state;
        Dictionary<GameState, List<Button>> buttons;

        Button endturnBttn;//, rangeBttn, soldierBttn, tankBttn;
        Window confirmAttackWindow, hudWindow; bool attackConfirmed;
        List<Player> players; int pTurn;
        List<Tile> tilesInRange, attackRange;
        MouseControl mouse;
        #endregion Attributes

        #region Initalize / Load Content
        public Game()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
        }

        protected override void Initialize()
        {
            graphics.PreferredBackBufferHeight = 720;
            graphics.PreferredBackBufferWidth = 1280;
            graphics.IsFullScreen = false;
            graphics.ApplyChanges();

            this.IsMouseVisible = true;
            pTurn = 0;
            map = new Map(0);

            state = GameState.Menu;
            attackConfirmed = true;

            players = new List<Player>
            {
                new Player("Player1", Color.Multiply(Color.LightSkyBlue, .9f)),
                new Player("Player2", Color.Multiply(Color.PaleVioletRed, 1.2f))
            };
            Color bla = players[0].Color;
            bla.A = 255; players[0].Color = bla;
            bla = players[1].Color;
            bla.A = 255; players[1].Color = bla;

            base.Initialize();
        }

        protected void InitializeAfterLoadContent()
        {
            mouse = new MouseControl(new ImageObject(blank, 0, 0, 25, 25, spriteBatch));
            endturnBttn = new Button(blank, 0, Var.TOTAL_HEIGHT - 40, 120, 40, spriteBatch,
                new TextObject("End Turn", Vector2.Zero, normalFont, TextObject.STANDARD_COLOR, spriteBatch), EndTurn);
            pTurn = players.Count - 1;
            EndTurn(endturnBttn);

            buttons = new Dictionary<GameState, List<Button>>
            {
                { GameState.Menu,
                        new List<Button> {
                            new Button(blank, 100, 200, 300, 140, spriteBatch, new TextObject("Play", Vector2.Zero, normalFont, TextObject.STANDARD_COLOR, spriteBatch), null),//play button
                            new Button(blank, 100, 350, 300, 140, spriteBatch, new TextObject("Instructions", Vector2.Zero, normalFont, TextObject.STANDARD_COLOR, spriteBatch), null),//instructions button
                            new Button(blank, 100, 500, 300, 140, spriteBatch, new TextObject("Credits", Vector2.Zero, normalFont, TextObject.STANDARD_COLOR, spriteBatch), null),//credits button
                            new Button(blank, 500, 350, 300, 140, spriteBatch, new TextObject("Exit", Vector2.Zero, normalFont, TextObject.STANDARD_COLOR, spriteBatch), null)//exit button
                        }
                    },
                 { GameState.End,
                        new List<Button> {
                            new Button(blank, 912, 513, 300, 140, spriteBatch, new TextObject("Replay", Vector2.Zero, normalFont, TextObject.STANDARD_COLOR, spriteBatch), null),//replay button
                            new Button(blank, 62, 513, 300, 140, spriteBatch, new TextObject("Menu", Vector2.Zero, normalFont, TextObject.STANDARD_COLOR, spriteBatch), null),//menu button
                         }
                    }
            };

            players[0].AddUnit(NewUnit("Soldier", map.Tiles[0, 1]));
            players[0].AddUnit(NewUnit("Soldier", map.Tiles[0, 2]));
            players[0].AddUnit(NewUnit("Soldier", map.Tiles[0, 3]));
            players[0].AddUnit(NewUnit("Soldier", map.Tiles[0, 4]));
            players[0].AddUnit(NewUnit("Tank", map.Tiles[0, 5]));
            players[0].AddUnit(NewUnit("Tank", map.Tiles[0, 6]));
            players[0].AddUnit(NewUnit("Range", map.Tiles[0, 7]));
            players[0].AddUnit(NewUnit("Range", map.Tiles[0, 8]));

            pTurn = 1;
            players[1].AddUnit(NewUnit("Soldier", map.Tiles[9, 8]));
            players[1].AddUnit(NewUnit("Soldier", map.Tiles[9, 7]));
            players[1].AddUnit(NewUnit("Soldier", map.Tiles[9, 6]));
            players[1].AddUnit(NewUnit("Soldier", map.Tiles[9, 5]));
            players[1].AddUnit(NewUnit("Tank", map.Tiles[9, 4]));
            players[1].AddUnit(NewUnit("Tank", map.Tiles[9, 3]));
            players[1].AddUnit(NewUnit("Range", map.Tiles[9, 2]));
            players[1].AddUnit(NewUnit("Range", map.Tiles[9, 1]));
            players[1].Units.ForEach(unit => unit.Rotation += ImageObject.ONE_EIGHTY);
            pTurn = 0;
        }

        protected override void LoadContent()
        {
            // Create a new SpriteBatch, which can be used to draw textures.
            spriteBatch = new SpriteBatch(GraphicsDevice);
            blank = this.Content.Load<Texture2D>("Blank");

            #region Spritefonts
            largeFont = this.Content.Load<SpriteFont>("Spritefonts/Large");
            mediumFont = this.Content.Load<SpriteFont>("Spritefonts/Medium");
            normalFont = this.Content.Load<SpriteFont>("Spritefonts/Normal");
            smallFont = this.Content.Load<SpriteFont>("Spritefonts/Small");
            #endregion Spritefonts

            #region Game Sprites
            soldierNinjaTex = this.Content.Load<Texture2D>("Game Sprites/ninja_Soldier");
            tankNinjaTex = this.Content.Load<Texture2D>("Game Sprites/ninja_Tank");
            rangeNinjaTex = this.Content.Load<Texture2D>("Game Sprites/ninja_Range");

            soldierPandaTex = this.Content.Load<Texture2D>("Game Sprites/panda_Soldier");
            tankPandaTex = this.Content.Load<Texture2D>("Game Sprites/panda_Tank");
            rangePandaTex = this.Content.Load<Texture2D>("Game Sprites/panda_Range");

            forest = this.Content.Load<Texture2D>("Game Sprites/forest_tile");
            ground = this.Content.Load<Texture2D>("Game Sprites/ground_tile");
            mountain = this.Content.Load<Texture2D>("Game Sprites/mountain_tile");
            #endregion Game Sprites

            #region Menu
            playButton = this.Content.Load<Texture2D>("Menu/Play Button");
            instructButton = this.Content.Load<Texture2D>("Menu/Instruction Button");
            exitButton = this.Content.Load<Texture2D>("Menu/Exit Button");

            instruct = this.Content.Load<Texture2D>("Menu/Instructions");
            credits = this.Content.Load<Texture2D>("Menu/Credits");
            creditButton = this.Content.Load<Texture2D>("Menu/Credits Button");
            menu = this.Content.Load<Texture2D>("Menu/Menu");
            backButton = this.Content.Load<Texture2D>("Menu/Back");

            replayButton = this.Content.Load<Texture2D>("Menu/Replay Button");
            end = this.Content.Load<Texture2D>("Menu/End");
            #endregion Menu

            InitializeAfterLoadContent();
        }
        #endregion Initalize / Load Content

        #region Update
        protected override void Update(GameTime gameTime)
        {
            mouse.Update();

            switch (state)
            {
                #region GameState.Game
                case GameState.Game:
                    if (currentUnit != null && currentUnit.PhaseDone)
                    {
                        ClearCurrentUnitData();
                    }

                    // Updates units, and if current player moved all units, 
                    bool noMoreActions = false;
                    foreach (Unit unit in players[pTurn].Units)
                    {
                        if (attackConfirmed)
                            unit.Update();
                        if (unit.PhaseDone == false)
                            noMoreActions = true;
                    }
                    if (noMoreActions == false)
                        EndTurn(null);

                    // After a unit moves, this updates tiles
                    if (currentUnit != null && tilesInRange != null && currentUnit.Moving == false && currentUnit.PhaseDone == false)
                    {
                        tilesInRange = map.FindUnitRange(currentUnit, out attackRange);
                    }

                    #region Mouse Clicked
                    if (mouse.SingleClick())
                    {
                        if (confirmAttackWindow != null)
                        {
                            if (confirmAttackWindow.Intersects(mouse.Rectangle) == false)
                                CancelAttack(null);
                            else
                            {
                                mouse.SingleClicked = false;
                                foreach (Button bttn in confirmAttackWindow.Buttons)
                                {
                                    if (mouse.CheckIfClicked(bttn.Rectangle))
                                        bttn.Click();
                                }
                                mouse.SingleClicked = true;
                            }
                        }

                        else if (endturnBttn.Intersects(mouse.Rectangle))
                        {
                            endturnBttn.Click();
                        }
                        else if (currentUnit == null || (currentUnit != null && currentUnit.Moving == false))
                        {
                            Unit selectedUnit = null;

                            foreach (Tile tile in map.Tiles)
                            {
                                selectedUnit = tile.OccupiedBy;

                                if (tile.Intersects(mouse.Rectangle))
                                {
                                    // Select this unit
                                    if (selectedUnit != null && selectedUnit.Player == players[pTurn] && selectedUnit.CurrentPhase == Unit.Phase.Move)
                                    {
                                        if (currentUnit != null && currentUnit.CurrentPhase == Unit.Phase.Attack)
                                            currentUnit.CurrentPhase = Unit.Phase.Done;
                                        currentUnit = selectedUnit;
                                        currentTile = null;
                                        HudWindow();
                                        tilesInRange = map.FindUnitRange(currentUnit, out attackRange);
                                    }
                                    // Attack
                                    else if (currentUnit != null && (attackRange != null && attackRange.Contains(tile)) && selectedUnit != null && currentUnit.Player != selectedUnit.Player && currentUnit.PhaseDone == false)
                                    {
                                        if (map.IsTileInRange(currentUnit.Tile, tile, currentUnit.Range))
                                        {
                                            currentUnit.UnitToAttack = selectedUnit;
                                            OpenConfirmAttackWindow();
                                        }
                                        else
                                        {
                                            List<Tile> tempList = map.FindPath(currentUnit.Tile, tile, (int)currentUnit.MovementLeft + currentUnit.Range);
                                            for (int i = 0; i < currentUnit.Range; i++)
                                                tempList.RemoveAt(tempList.Count - 1);
                                            currentTile = tempList.Last();

                                            currentUnit.Path = tempList;

                                            currentUnit.UnitToAttack = selectedUnit;
                                            OpenConfirmAttackWindow();
                                        }
                                    }
                                    // Make tile target
                                    else if (currentUnit != null && selectedUnit == null)
                                    {
                                        if (tilesInRange != null && tilesInRange.Contains(tile))
                                        {
                                            currentTile = tile;
                                            currentUnit.Path = map.FindPath(currentUnit.Tile, currentTile, (int)currentUnit.MovementLeft);
                                        }
                                        else if (attackRange != null && attackRange.Contains(tile) && currentUnit.CurrentPhase == Unit.Phase.Move)
                                        {
                                            List<Tile> tempList = map.FindPath(currentUnit.Tile, tile, (int)currentUnit.MovementLeft + currentUnit.Range);
                                            for (int i = 0; i < currentUnit.Range; i++)
                                                tempList.RemoveAt(tempList.Count - 1);
                                            currentTile = tempList.Last();
                                            currentUnit.Path = tempList;
                                        }
                                        else
                                        {
                                            if (currentUnit.CurrentPhase == Unit.Phase.Attack)
                                            {
                                                currentUnit.CurrentPhase = Unit.Phase.Done;
                                            }
                                            ClearCurrentUnitData();
                                        }
                                    }
                                    // Select Enemy Unit
                                    else if (selectedUnit != null)
                                    {
                                        ClearCurrentUnitData();
                                        currentUnit = selectedUnit;
                                        HudWindow();
                                        tilesInRange = map.FindUnitRange(selectedUnit, out attackRange);
                                        currentUnit = null;
                                    }
                                    else
                                    {
                                        ClearCurrentUnitData();
                                    }
                                }
                            }
                        }
                    }
                    else if (mouse.SingleClicked == false && mouse.RightClick)
                    {
                        if (currentUnit != null && currentUnit.PhaseDone == false)
                        {
                            currentUnit.Tile = currentUnit.TileBeforeMoving;
                            currentTile = null;
                            tilesInRange = map.FindUnitRange(currentUnit, out attackRange);
                            currentUnit.Refresh();
                        }
                    }
                    #endregion Mouse Clicked

                    #region Check for lose condition(s)
                    foreach (Player player in players)
                    {
                        bool lost = true;
                        foreach (Unit unit in player.Units)
                        {
                            if (unit.IsActive)
                            {
                                lost = false;
                                break;
                            }
                        }
                        if (lost || player.Units.Count == 0)
                        {
                            state = GameState.End;
                            graphics.PreferredBackBufferHeight = 720;
                            graphics.PreferredBackBufferWidth = 1280;
                            graphics.ApplyChanges();
                            break;
                        }
                    }
                    #endregion Check for lose condition(s)

                    break;
                #endregion GameState.Game

                #region GameState.GameBase
                case GameState.GameBase:

                    #region Mouse Clicked
                    if (mouse.SingleClick())
                    {

                    }
                    #endregion Mouse Clicked

                    break;
                #endregion GameState.GameBase

                #region Everything Else
                case GameState.Menu:
                    if (mouse.CheckIfClicked(buttons[state][0].Rectangle))
                    {
                        state = GameState.Game;
                        graphics.PreferredBackBufferHeight = Var.TOTAL_HEIGHT;
                        graphics.PreferredBackBufferWidth = Var.TOTAL_WIDTH;
                        graphics.ApplyChanges();
                    }
                    else if (mouse.CheckIfClicked(buttons[state][1].Rectangle))
                    {
                        state = GameState.Instructions;
                    }
                    else if (mouse.CheckIfClicked(buttons[state][2].Rectangle))
                    {
                        state = GameState.Credits;
                    }
                    else if (mouse.CheckIfClicked(buttons[state][3].Rectangle))
                    {
                        Environment.Exit(0);
                    }
                    break;
                case GameState.Start:
                    state = GameState.Game;
                    break;
                case GameState.Instructions:
                    if (mouse.SingleClick())
                    {
                        state = GameState.Menu;
                    }
                    break;
                case GameState.Credits:
                    if (mouse.SingleClick())
                    {
                        state = GameState.Menu;
                    }
                    break;
                case GameState.End:
                    if (mouse.CheckIfClicked(buttons[state][0].Rectangle))
                    {
                        state = GameState.Game;
                        InitializeAfterLoadContent();
                    }
                    else if (mouse.CheckIfClicked(buttons[state][1].Rectangle))
                    {
                        state = GameState.Menu;
                        Initialize();
                        LoadContent();
                        InitializeAfterLoadContent();
                    }
                    break;
                #endregion Everything Else
            }

            base.Update(gameTime);
        }
        #endregion Update

        #region Draw
        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.CornflowerBlue);
            spriteBatch.Begin();

            switch (state)
            {
                #region GameState.Game
                case GameState.Game:
                    foreach (Tile tile in map.Tiles)
                    {
                        if (tile.TileType == Tile.Type.Normal)
                        {
                            if (tile.Weight == 1)
                                spriteBatch.Draw(ground, tile.Rectangle, Color.White);
                            else
                                spriteBatch.Draw(forest, tile.Rectangle, Color.White);
                        }
                        if (tile.TileType == Tile.Type.Blocked)
                            spriteBatch.Draw(mountain, tile.Rectangle, Color.White);
                        if (tile.OccupiedBy != null && tile.OccupiedBy.Player == players[pTurn] && tile.OccupiedBy.PhaseDone == false)
                            spriteBatch.Draw(blank, tile.Rectangle, tile.OccupiedBy.Player.Color);
                    }

                    if (tilesInRange != null)
                    {
                        foreach (Tile tile in tilesInRange)
                        {
                            spriteBatch.Draw(blank, tile.Rectangle, Color.FromNonPremultiplied(255, 215, 0, 100));
                        }
                    }

                    if (attackRange != null)
                    {
                        if (currentUnit != null && currentUnit.CurrentPhase == Unit.Phase.Attack)
                        {
                            Color pulseColor = Color.FromNonPremultiplied(255, 69, 0, 100);
                            double pulseSpeed = 2; //Note: 1.0 is base
                            pulseColor = Color.Multiply(pulseColor, 1.0f + (float)(.5 * Math.Sin(gameTime.TotalGameTime.TotalSeconds * pulseSpeed)));
                            foreach (Tile tile in attackRange)
                                spriteBatch.Draw(blank, tile.Rectangle, pulseColor);
                        }
                        else
                        {
                            foreach (Tile tile in attackRange)
                                spriteBatch.Draw(blank, tile.Rectangle, Color.FromNonPremultiplied(255, 69, 0, 100));
                        }
                    }

                    foreach (Tile tile in map.Tiles)
                    {
                        if (tile.Intersects(mouse.Rectangle))
                            ImageObject.DrawRectangleOutline(tile.Rectangle, 2, Color.Navy, blank, spriteBatch);
                    }

                    if (currentUnit != null && currentUnit.Path != null)
                    {
                        Color pathColor = Color.Multiply(currentUnit.Player.Color, 0.65f); pathColor.A = (byte)255;
                        foreach (Tile tile in currentUnit.Path)
                        {
                            if (tile != currentUnit.Path.First())
                                spriteBatch.Draw(blank, tile.Rectangle, pathColor);
                        }
                    }
                    if (currentUnit != null && currentUnit.Tile != null && currentUnit.Moving == false)
                        spriteBatch.Draw(blank, currentUnit.Tile.Rectangle, Color.Green);
                    if (currentTile != null)
                        spriteBatch.Draw(blank, currentTile.Rectangle, Color.Orange);

                    // Draws Units
                    players.ForEach(player => player.Draw());

                    if (confirmAttackWindow != null) {
                        confirmAttackWindow.Draw();
                        confirmAttackWindow.DrawRectangleOutline(9, Color.DarkBlue, blank);
                    }
                    if (hudWindow != null)
                        hudWindow.Draw();

                    endturnBttn.Draw();
                #endregion GameState.Game

                #region GameState.GameBase
                    if (state == GameState.GameBase)
                    {
                        spriteBatch.Draw(blank, Var.PLAY_AREA, Var.OUTER_GRAY);
                    }
                    break;
                #endregion GameState.GameBase

                #region Everything Else
                case GameState.Menu:
                    spriteBatch.Draw(menu, new Rectangle(0, 0, graphics.PreferredBackBufferWidth, graphics.PreferredBackBufferHeight), Color.White);
                    spriteBatch.Draw(playButton, buttons[state][0].Rectangle, Color.White);
                    spriteBatch.Draw(instructButton, buttons[state][1].Rectangle, Color.White);
                    spriteBatch.Draw(creditButton, buttons[state][2].Rectangle, Color.White);
                    spriteBatch.Draw(exitButton, buttons[state][3].Rectangle, Color.White);
                    break;
                case GameState.Start:

                    break;
                case GameState.Instructions:
                    spriteBatch.Draw(instruct, new Rectangle(0, 0, graphics.PreferredBackBufferWidth, graphics.PreferredBackBufferHeight), Color.White);
                    spriteBatch.Draw(backButton, new Rectangle(912, 513, 300, 140), Color.White);

                    break;
                case GameState.Credits:
                    spriteBatch.Draw(credits, new Rectangle(0, 0, graphics.PreferredBackBufferWidth, graphics.PreferredBackBufferHeight), Color.White);
                    spriteBatch.Draw(backButton, new Rectangle(912, 513, 300, 140), Color.White);
                    break;
                case GameState.End:
                    spriteBatch.Draw(end, new Rectangle(0, 0, graphics.PreferredBackBufferWidth, graphics.PreferredBackBufferHeight), Color.White);
                    spriteBatch.Draw(replayButton, buttons[state][0].Rectangle, Color.White);
                    spriteBatch.Draw(backButton, buttons[state][1].Rectangle, Color.White);
                    break;
                #endregion Everything Else
            }

            spriteBatch.End();
            base.Draw(gameTime);
        }
        #endregion Draw

        #region New Units
        /// <summary> Returns a new unit of requested type. </summary>
        /// <param name="unitType">"SOLDIER" | "TANK" | "RANGE" (Caps don't matter).</param>
        private Unit NewUnit(string unitType, Tile tile)
        {
            string type = unitType.ToUpper().Trim();

            #region Soldier
            if (type == "SOLDIER")
            {
                if(pTurn == 0)
                    return new Unit_Soldier(6, 2, 6, 1, 90, soldierNinjaTex, tile, 30, spriteBatch);
                else if(pTurn == 1)
                    return new Unit_Soldier(6, 2, 6, 1, 90, soldierPandaTex, tile, 30, spriteBatch);
            }
            #endregion Soldier

            #region Tank
            else if (type == "TANK")
            {
                if(pTurn == 0)
                    return new Unit_Tank(6, 2, 4, 2, 90, tankNinjaTex, tile, 30, spriteBatch);
                else if(pTurn == 1)
                    return new Unit_Tank(6, 2, 4, 2, 90, tankPandaTex, tile, 30, spriteBatch);
            }
            #endregion Tank

            #region Range
            else if (type == "RANGE")
            {
                if(pTurn == 0)
                    return new Unit_Ranged(6, 2, 5, 3, 90, rangeNinjaTex, tile, 30, spriteBatch);
                else if(pTurn == 1)
                    return new Unit_Ranged(6, 2, 5, 3, 90, rangePandaTex, tile, 30, spriteBatch);
            }
            #endregion Range

            return null; // Should never happen.
        }
        #endregion New Units

        #region Events
        private void EndTurn(Button bttn)
        {
            if (currentUnit == null || (currentUnit != null && currentUnit.Moving == false))
            {
                ClearCurrentUnitData();
                players[pTurn].Units.ForEach(unit => unit.Refresh());
                pTurn = (pTurn + 1) % players.Count;

                if (pTurn == 0)
                {
                    endturnBttn.Color = Color.Blue;
                }
                else if (pTurn == 1)
                {
                    endturnBttn.Color = Color.Red;
                }
                else
                {
                    endturnBttn.Color = Color.Black;
                    endturnBttn.Message.Message = "Something Wrong Here";
                }
            }
        }

        private void ConfirmAttack(Button bttn)
        {
            attackConfirmed = true;
            confirmAttackWindow = null;
        }

        private void CancelAttack(Button bttn)
        {
            currentUnit.UnitToAttack = null;
            currentUnit.Path = null;
            currentTile = null;
            attackConfirmed = true;
            confirmAttackWindow = null;
        }
        #endregion Events

        #region Other
        private void ClearCurrentUnitData()
        {
            if (currentUnit != null && currentUnit.CurrentPhase == Unit.Phase.Attack)
                currentUnit.CurrentPhase = Unit.Phase.Done;
            currentUnit = null;
            tilesInRange = null;
            attackRange = null;
            currentTile = null;
            hudWindow = null;
        }

        private void OpenConfirmAttackWindow()
        {
            attackConfirmed = false;

            int width = 250, height = 270, bttnWidth = 65, bttnHeight = 35;
            confirmAttackWindow = new Window(Var.PLAY_AREA.Center.X - width / 2, Var.PLAY_AREA.Center.Y - height / 2, width, height, spriteBatch, blank, null, null);
            confirmAttackWindow.IsActive = true; confirmAttackWindow.Color = Color.LightGray;
            int xL = (int)confirmAttackWindow.X, yL = (int)confirmAttackWindow.Y;

            Button tempBttn;
            confirmAttackWindow.Buttons.Add(tempBttn = new Button(blank, (int)(xL + (width / 4.0f) - (bttnWidth / 2.0f)), (int)confirmAttackWindow.Bottom - bttnHeight - 5, bttnWidth, bttnHeight, spriteBatch, new TextObject("Fight", Vector2.Zero, normalFont, TextObject.STANDARD_COLOR, spriteBatch), ConfirmAttack));
            tempBttn.Color = Color.Black;
            confirmAttackWindow.Buttons.Add(tempBttn = new Button(blank, (int)(xL + (width / 4.0f * 3.0f) - (bttnWidth / 2.0f)), (int)confirmAttackWindow.Bottom - bttnHeight - 5, bttnWidth, bttnHeight, spriteBatch, new TextObject("Back", Vector2.Zero, normalFont, TextObject.STANDARD_COLOR, spriteBatch), CancelAttack));
            tempBttn.Color = Color.Black;
            confirmAttackWindow.Buttons.Add(tempBttn = new Button(blank, 0, yL, 5, height, spriteBatch, null, null));
            tempBttn.CenterX = confirmAttackWindow.CenterX; tempBttn.Color = Color.DarkOliveGreen;

            TextObject tempText;
            Unit tempUnit = currentUnit, otherUnit = currentUnit.UnitToAttack; // Should not be null.
            Color tempColor = Color.Multiply(tempUnit.Player.Color, .75f); tempColor.A = (byte)255;
            // Left side = unit being attacked ||| Right side = unit attacking
            int columnCenterX = (int)(xL + (width / 4.0f));
            for (int i = 0; i < 2; i++)
            {
                confirmAttackWindow.TextObjects.Add(tempText = new TextObject(tempUnit.Name, new Vector2(0, yL), largeFont, tempColor, spriteBatch));
                tempText.CenterX = columnCenterX;

                confirmAttackWindow.Buttons.Add(tempBttn = new Button(blank, 0, (int)tempText.Bottom, (int)(width / 2 * 0.9f), 2, spriteBatch, null, null));
                tempBttn.CenterX = columnCenterX; tempBttn.Color = tempColor;

                confirmAttackWindow.TextObjects.Add(tempText = new TextObject("Health\n" + tempUnit.Health + "\nDamage\n" + "" + "\nAttack\nRange\n" + tempUnit.Range, new Vector2(0, tempBttn.Bottom + 5), normalFont, tempColor, spriteBatch));
                tempText.CenterX = columnCenterX;
                
                int dmgDif = tempUnit.GetUnitVsUnitDamage(otherUnit) - tempUnit.Damage;
                float dmgMsgHeight = tempText.Y + (tempText.Height / 7) * 3;
                bool inRange = true; Tile curUnitCurTile = tempUnit.Tile; tempUnit.Tile = currentTile; inRange = tempUnit.InRange(otherUnit); tempUnit.Tile = curUnitCurTile;
                if (inRange == false) {
                    confirmAttackWindow.TextObjects.Add(tempText = new TextObject("---", new Vector2(0, dmgMsgHeight), normalFont, tempColor, spriteBatch));
                    tempText.CenterX = columnCenterX;
                }else if (dmgDif == 0) {
                    confirmAttackWindow.TextObjects.Add(tempText = new TextObject("" + tempUnit.Damage, new Vector2(0, dmgMsgHeight), normalFont, tempColor, spriteBatch));
                    tempText.CenterX = columnCenterX;
                }else{
                    // Note, each piece should be 1 character
                    string[] stringPieces = { "" + tempUnit.Damage, "-", "" + Math.Abs(dmgDif), "=", "" + tempUnit.GetUnitVsUnitDamage(otherUnit) };
                    Color[] colors = { Color.Black, Color.Red, Color.Red, Color.Black, tempColor };

                    if (dmgDif > 0) {
                        stringPieces[1] = "+";
                        colors[1] = colors[2] = Color.Green;
                    }
                    float xStart;
                    string msg = "";
                    stringPieces.ToList().ForEach(part => msg += part);
                    xStart = columnCenterX - (normalFont.MeasureString(msg).X / 2);

                    for (int v = 0; v < stringPieces.Length; v++)
                    {
                        confirmAttackWindow.TextObjects.Add(tempText =
                            new TextObject(stringPieces[v],
                                new Vector2(xStart + normalFont.MeasureString(msg.Substring(0, v)).X, dmgMsgHeight),
                                normalFont, colors[v], spriteBatch));
                    }
                }

                otherUnit = tempUnit;
                tempUnit = currentUnit.UnitToAttack;
                tempColor = Color.Multiply(tempUnit.Player.Color, .75f); tempColor.A = (byte)255;
                columnCenterX = (int)(xL + (width / 4.0f * 3));
            }
        }

        private void HudWindow()
        {
            int width = 250 / 2, height = 270;
            Color tempColor = Color.Multiply(currentUnit.Player.Color, .75f); tempColor.A = (byte)255;

            hudWindow = new Window(Var.TOTAL_WIDTH - width, 0, width, height, spriteBatch, blank, null, null);
            hudWindow.IsActive = true; hudWindow.Color = Color.LightGray;
            int xL = (int)hudWindow.X, yL = (int)hudWindow.Y;
            int columnCenterX = (int)(xL + (width / 2.0f));
            
            TextObject tempText;
            Unit tempUnit = currentUnit;
            hudWindow.TextObjects.Add(tempText = new TextObject(tempUnit.Name, new Vector2(0, yL), largeFont, tempColor, spriteBatch));
            tempText.CenterX = columnCenterX;

            Button tempBttn;
            hudWindow.Buttons.Add(tempBttn = new Button(blank, 0, (int)tempText.Bottom, (int)(width * 0.9f), 2, spriteBatch, null, null));
            tempBttn.CenterX = columnCenterX; tempBttn.Color = tempColor;

            hudWindow.TextObjects.Add(tempText = new TextObject("Health\n" + tempUnit.Health + "\nAttack\nRange\n" + tempUnit.Range, new Vector2(0, tempBttn.Bottom + 5), normalFont, tempColor, spriteBatch));
            tempText.CenterX = columnCenterX;

            hudWindow.Height = (int)(tempText.Bottom - hudWindow.Y);
        }
        #endregion .
    }
}